package com.ruoyi.mongo.cet4.repository.impl;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.util.Assert;

import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
 * 动态集合Repository实现类
 * 支持在运行时指定集合名进行CRUD操作
 */
public class DynamicCollectionRepositoryImpl<T, ID> implements PagingAndSortingRepository<T, ID> {

    // 实体类类型
    private final Class<T> domainType;
    // MongoDB操作模板
    private final MongoOperations mongoOperations;
    // 默认集合名（从实体类注解获取）
    private final String defaultCollectionName;

    /**
     * 构造函数
     * @param domainType 实体类类型
     * @param mongoOperations MongoDB操作模板
     */
    public DynamicCollectionRepositoryImpl(Class<T> domainType, MongoOperations mongoOperations) {
        Assert.notNull(domainType, "实体类类型不能为null");
        Assert.notNull(mongoOperations, "MongoOperations不能为null");

        this.domainType = domainType;
        this.mongoOperations = mongoOperations;
        this.defaultCollectionName = mongoOperations.getCollectionName(domainType);
    }

    // ------------------------------ 动态集合操作方法 ------------------------------

    /**
     * 保存实体到指定集合
     */
    public <S extends T> S save(S entity, String collectionName) {
        Assert.notNull(entity, "实体不能为null");
        Assert.hasText(collectionName, "集合名不能为null或空");

        return mongoOperations.save(entity, collectionName);
    }

    /**
     * 批量保存实体到指定集合
     */
    public <S extends T> Iterable<S> saveAll(Iterable<S> entities, String collectionName) {
        Assert.notNull(entities, "实体集合不能为null");
        Assert.hasText(collectionName, "集合名不能为null或空");

        List<S> entityList = StreamSupport.stream(entities.spliterator(), false)
                .collect(Collectors.toList());

        if (!entityList.isEmpty()) {
            mongoOperations.insert(entityList, collectionName);
        }
        return entityList;
    }

    /**
     * 根据ID从指定集合查询
     */
    public Optional<T> findById(ID id, String collectionName) {
        Assert.notNull(id, "ID不能为null");
        Assert.hasText(collectionName, "集合名不能为null或空");

        T entity = mongoOperations.findById(id, domainType, collectionName);
        return Optional.ofNullable(entity);
    }

    /**
     * 判断ID在指定集合中是否存在
     */
    public boolean existsById(ID id, String collectionName) {
        Assert.notNull(id, "ID不能为null");
        Assert.hasText(collectionName, "集合名不能为null或空");

        Query query = Query.query(Criteria.where("_id").is(id));
        return mongoOperations.exists(query, collectionName);
    }

    /**
     * 查询指定集合的所有实体
     */
    public Iterable<T> findAll(String collectionName) {
        Assert.hasText(collectionName, "集合名不能为null或空");
        return mongoOperations.findAll(domainType, collectionName);
    }

    /**
     * 根据ID集合从指定集合查询
     */
    public Iterable<T> findAllById(Iterable<ID> ids, String collectionName) {
        Assert.notNull(ids, "ID集合不能为null");
        Assert.hasText(collectionName, "集合名不能为null或空");

        List<ID> idList = StreamSupport.stream(ids.spliterator(), false)
                .collect(Collectors.toList());

        if (idList.isEmpty()) {
            return Collections.emptyList();
        }

        Query query = Query.query(Criteria.where("_id").in(idList));
        return mongoOperations.find(query, domainType, collectionName);
    }

    /**
     * 统计指定集合的记录数
     */
    public long count(String collectionName) {
        Assert.hasText(collectionName, "集合名不能为null或空");
        return mongoOperations.count(new Query(), collectionName);
    }

    /**
     * 从指定集合删除指定ID的实体
     */
    public void deleteById(ID id, String collectionName) {
        Assert.notNull(id, "ID不能为null");
        Assert.hasText(collectionName, "集合名不能为null或空");

        Query query = Query.query(Criteria.where("_id").is(id));
        mongoOperations.remove(query, collectionName);
    }

    /**
     * 从指定集合删除实体
     */
    public void delete(T entity, String collectionName) {
        Assert.notNull(entity, "实体不能为null");
        Assert.hasText(collectionName, "集合名不能为null或空");

        mongoOperations.remove(entity, collectionName);
    }

    /**
     * 从指定集合批量删除指定ID的实体
     */
    public void deleteAllById(Iterable<? extends ID> ids, String collectionName) {
        Assert.notNull(ids, "ID集合不能为null");
        Assert.hasText(collectionName, "集合名不能为null或空");

        List<ID> idList = StreamSupport.stream(ids.spliterator(), false)
                .collect(Collectors.toList());

        if (!idList.isEmpty()) {
            Query query = Query.query(Criteria.where("_id").in(idList));
            mongoOperations.remove(query, collectionName);
        }
    }

    /**
     * 从指定集合批量删除实体
     */
    public void deleteAll(Iterable<? extends T> entities, String collectionName) {
        Assert.notNull(entities, "实体集合不能为null");
        Assert.hasText(collectionName, "集合名不能为null或空");

        entities.forEach(entity -> delete(entity, collectionName));
    }

    /**
     * 删除指定集合的所有记录
     */
    public void deleteAll(String collectionName) {
        Assert.hasText(collectionName, "集合名不能为null或空");
        mongoOperations.remove(new Query(), collectionName);
    }

    /**
     * 从指定集合排序查询
     */
    public Iterable<T> findAll(Sort sort, String collectionName) {
        Assert.notNull(sort, "排序条件不能为null");
        Assert.hasText(collectionName, "集合名不能为null或空");

        Query query = new Query().with(sort);
        return mongoOperations.find(query, domainType, collectionName);
    }

    /**
     * 从指定集合分页查询
     */
    public Page<T> findAll(Pageable pageable, String collectionName) {
        Assert.notNull(pageable, "分页条件不能为null");
        Assert.hasText(collectionName, "集合名不能为null或空");

        Query query = new Query().with(pageable);
        List<T> content = mongoOperations.find(query, domainType, collectionName);

        // 计算总条数（移除分页参数）
        long total = mongoOperations.count(Query.of(query).limit(-1).skip(-1), collectionName);

        return PageableExecutionUtils.getPage(content, pageable, () -> total);
    }

    /**
     * 按字段条件从指定集合查询
     */
    public List<T> findByField(String field, Object value, String collectionName) {
        Assert.hasText(field, "字段名不能为null或空");
        Assert.notNull(value, "字段值不能为null");
        Assert.hasText(collectionName, "集合名不能为null或空");

        Query query = Query.query(Criteria.where(field).is(value));
        return mongoOperations.find(query, domainType, collectionName);
    }

    // ------------------------------ 实现父接口方法（使用默认集合） ------------------------------

//    @Override
//    public <S extends T> S save(S entity) {
//        return save(entity, defaultCollectionName);
//    }
//
//    @Override
//    public <S extends T> Iterable<S> saveAll(Iterable<S> entities) {
//        return saveAll(entities, defaultCollectionName);
//    }
//
//    @Override
//    public Optional<T> findById(ID id) {
//        return findById(id, defaultCollectionName);
//    }
//
//    @Override
//    public boolean existsById(ID id) {
//        return existsById(id, defaultCollectionName);
//    }
//
//    @Override
//    public Iterable<T> findAll() {
//        return findAll(defaultCollectionName);
//    }
//
//    @Override
//    public Iterable<T> findAllById(Iterable<ID> ids) {
//        return findAllById(ids, defaultCollectionName);
//    }
//
//    @Override
//    public long count() {
//        return count(defaultCollectionName);
//    }
//
//    @Override
//    public void deleteById(ID id) {
//        deleteById(id, defaultCollectionName);
//    }
//
//    @Override
//    public void delete(T entity) {
//        delete(entity, defaultCollectionName);
//    }
//
//    @Override
//    public void deleteAllById(Iterable<? extends ID> ids) {
//        deleteAllById(ids, defaultCollectionName);
//    }
//
//    @Override
//    public void deleteAll(Iterable<? extends T> entities) {
//        deleteAll(entities, defaultCollectionName);
//    }
//
//    @Override
//    public void deleteAll() {
//        deleteAll(defaultCollectionName);
//    }

    @Override
    public Iterable<T> findAll(Sort sort) {
        return findAll(sort, defaultCollectionName);
    }

    @Override
    public Page<T> findAll(Pageable pageable) {
        return findAll(pageable, defaultCollectionName);
    }

    // ------------------------------ 未实现的扩展方法（如需使用可自行实现） ------------------------------

//    @Override
//    public <S extends T> Optional<S> findOne(Example<S> example) {
//        throw new UnsupportedOperationException("动态集合查询暂不支持Example查询");
//    }
//
//    @Override
//    public <S extends T> List<S> findAll(Example<S> example) {
//        throw new UnsupportedOperationException("动态集合查询暂不支持Example查询");
//    }
//
//    @Override
//    public <S extends T> List<S> findAll(Example<S> example, Sort sort) {
//        throw new UnsupportedOperationException("动态集合查询暂不支持Example查询");
//    }
//
//    @Override
//    public <S extends T> Page<S> findAll(Example<S> example, Pageable pageable) {
//        throw new UnsupportedOperationException("动态集合查询暂不支持Example查询");
//    }
//
//    @Override
//    public <S extends T> long count(Example<S> example) {
//        throw new UnsupportedOperationException("动态集合查询暂不支持Example查询");
//    }
//
//    @Override
//    public <S extends T> boolean exists(Example<S> example) {
//        throw new UnsupportedOperationException("动态集合查询暂不支持Example查询");
//    }
//
//    @Override
//    public <S extends T, R> R findBy(Example<S> example, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction) {
//        throw new UnsupportedOperationException("动态集合查询暂不支持FluentQuery");
//    }
}

